AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

function ENT:Initialize()
	self.Entity:SetMaterial( "models/props_combine/tprotato1_sheet" )
	
	self.Entity:PhysicsInit( SOLID_VPHYSICS )
	self.Entity:SetMoveType( MOVETYPE_VPHYSICS )
	self.Entity:SetSolid( SOLID_VPHYSICS )
	
	self.HP = 0
	self.DomeOn = false
	self.Active = false
	self.RegenAmount = self.MaxHP / math.log10(self.MaxHP) / 40
	self.EnergyDemand = self.Radius * self.MaxHP / 200000
	self.Reinforced = false
	
	self.WireDebugName = self.PrintName
	self.Inputs = CDE_Wire_CreateInputs(self.Entity, { "Power", "Reinforce" })
	self.Outputs = CDE_Wire_CreateOutputs(self.Entity, { "Integrity" })
	
	CDE_RD_AddResource(self, "energy", 0)
	
	self.Entity:GetPhysicsObject():Wake()
	self.Entity:NextThink(CurTime() + 1)
end

function ENT:ReduceIntegrity(damage)
	local lostproportion
	if self.Reinforced then
		lostproportion = math.Clamp((damage * 0.75) / self.HP, 0, 1)
		self.HP = self.HP - (damage * 0.75)
	else
		lostproportion = math.Clamp(damage / self.HP, 0, 1)
		self.HP = self.HP - damage
	end
	if self.HP <= 0 then
		self.Entity:Deplete()
	end
	return lostproportion
end

function ENT:Deplete()
	self.HP = 0
	self.DomeOn = false
	if (self.Dome != nil && self.Dome:IsValid()) then self.Dome:Remove() end
end

function ENT:Regenerate()
	if self.Reinforced && (CDE_RD_GetResourceAmount(self, "energy") >= ((self.EnergyDemand * 5) / 4)) then
		self.HP = math.Clamp(self.HP + (self.RegenAmount * 2), 0, self.MaxHP)
		CDE_RD_ConsumeResource(self, "energy", (self.EnergyDemand * 5) / 4)
	elseif (CDE_RD_GetResourceAmount(self, "energy") >= self.EnergyDemand / 4) then
		self.HP = math.Clamp(self.HP + self.RegenAmount, 0, self.MaxHP)
		CDE_RD_ConsumeResource(self, "energy", self.EnergyDemand / 4)
	else
		self.Entity:Deplete()
	end
end

function ENT:PowerOn()
	self.Active = true
end

function ENT:PowerOff()
	self.Active = false
	self.DomeOn = false
	if (self.Dome != nil && self.Dome:IsValid()) then self.Dome:Remove() end
end

function ENT:ProjectDome()
	local s = ents.Create("shield_dome")
	s.Radius = self.Radius
	s:SetPos(self.Entity:GetPos())
	s:SetAngles(self.Entity:GetAngles())
	s:SetParent(self.Entity)
	s.DomeMaterial = self.DomeMaterial
	s.ImpactColor = self.ImpactColor
	s.ImpactEffect = self.ImpactMaterial
	s.Formdirection = self.Formdirection
	s:SetPlayer(self.Entity:GetPlayer())
	s:Spawn()
	self.Dome = s
	self.DomeOn = true
end

function ENT:CheckDomeValidity() --Makes sure the dome is still there and hasn't been inadvertently removed
	if (self.Dome != nil) and (not self.Dome:IsValid()) and self.DomeOn then
		self.Entity:ProjectDome()
	end
end

function ENT:Think()
	local activetext = "Inactive"
	if (self.Active) then
		if (!self.DomeOn) then
			if self.HP == self.MaxHP then self.Entity:ProjectDome() end	
		end
		self.Entity:Regenerate()
		activetext = "Active"
		self.Entity:CheckDomeValidity()
	end
	local energyrequirement
	if not self.Reinforced then energyrequirement = self.EnergyDemand
	else energyrequirement = (self.EnergyDemand * 5) end
	local overlaytxt = activetext .. "\nIntegrity: " .. math.Round((self.HP / self.MaxHP)*100) .. "\nDe: " .. energyrequirement
	self.Entity:SetNetworkedString( "GModOverlayText", overlaytxt )
	self.Entity:NextThink(CurTime() + 0.25)
	CDE_Wire_TriggerOutput(self.Entity, "Integrity", math.Round((self.HP / self.MaxHP)*100))
	return true
end

function ENT:TriggerInput(k,v)
	if(k=="Power") then
		if(v >= 1) then
			self:PowerOn()
		else
			self:Deplete()
			self:PowerOff()
		end
	elseif (k == "Reinforce") then
		self.Reinforced = util.tobool(v)
	end
end

function ShieldDomeDuplicate(player, position, angles, maxHP, radius, material, color, model)
	local newentity = ents.Create("shield_bubble_generator")
	newentity:SetPos(position)
	newentity:SetAngles(angles)
	newentity:SetPlayer(player)
	newentity.MaxHP = maxHP
	newentity.Radius = radius
	newentity.DomeMaterial = material
	newentity.ImpactColor = color
	newentity:SetPlayer(player)
	newentity:SetModel(model)
	newentity:Spawn()
	return newentity
end

function ENT:PreEntityCopy()
	CDE_RD_BuildDupeInfo(self.Entity)
	if not (WireAddon == nil) then
		local DupeInfo = WireLib.BuildDupeInfo(self.Entity)
		if DupeInfo then
			duplicator.StoreEntityModifier( self.Entity, "WireDupeInfo", DupeInfo )
		end
	end
end

function ENT:PostEntityPaste( Player, Ent, CreatedEntities )
	CDE_RD_ApplyDupeInfo(Ent, CreatedEntities)
	if not (WireAddon == nil) and (Ent.EntityMods) and (Ent.EntityMods.WireDupeInfo) then
		WireLib.ApplyDupeInfo(Player, Ent, Ent.EntityMods.WireDupeInfo, function(id) return CreatedEntities[id] end)
	end
end

duplicator.RegisterEntityClass("shield_bubble_generator", ShieldDomeDuplicate, "pos", "ang", "MaxHP", "Radius", "DomeMaterial", "ImpactColor", "Model")